<template>
  <div id="appd">
    <!-- <button id="loadUrlBtn" class="btn btn-primary">
      <i class="fas fa-link"></i> 加载DICOM URL
    </button> -->
    <!-- 主要内容区域 -->
    <main class="main-content">
      <!-- 侧边栏 - 序列列表 -->
      <div class="sidebar">
        <div class="series-list" id="seriesList">
          <div
            v-for="series in seriesList"
            :key="series.seriesUID"
            class="series-item"
            :class="{ active: currentSeriesUID === series.seriesUID }"
            @click="selectSeries(series.seriesUID)"
          >
            <div class="series-thumbnail" v-if="series.thumbnail">
              <img :src="series.thumbnail" alt="Series thumbnail" />
            </div>
            <div class="series-content">
              <div class="series-title">{{
                series.seriesDescription || series.modality || '未知序列'
              }}</div>
              <div class="series-info"> {{ series.images.length }}# </div>
            </div>
          </div>
        </div>
      </div>

      <!-- 中央主体区域 -->
      <section class="viewer-container">
        <!-- 图像显示区域 -->
        <div class="viewer-main">
          <div id="dicomViewer" class="dicom-viewer" data-layout="1x1">
            <!-- 1x1 单视图 -->
            <div class="viewport-container layout-1x1">
              <div id="viewport1" class="viewport">
                <div class="viewer-placeholder">
                  <i class="fas fa-image"></i>
                  <p>选择序列以查看图像</p>
                </div>
              </div>
            </div>

            <!-- 1x2 双视图 -->
            <div class="viewport-container layout-1x2" style="display: none">
              <div id="viewport2" class="viewport">
                <div class="viewer-placeholder">
                  <i class="fas fa-image"></i>
                  <p>视图 1</p>
                </div>
              </div>
              <div id="viewport3" class="viewport">
                <div class="viewer-placeholder">
                  <i class="fas fa-image"></i>
                  <p>视图 2</p>
                </div>
              </div>
            </div>

            <!-- 2x2 四视图 -->
            <div class="viewport-container layout-2x2" style="display: none">
              <div id="viewport4" class="viewport">
                <div class="viewer-placeholder">
                  <i class="fas fa-image"></i>
                  <p>视图 1</p>
                </div>
              </div>
              <div id="viewport5" class="viewport">
                <div class="viewer-placeholder">
                  <i class="fas fa-image"></i>
                  <p>视图 2</p>
                </div>
              </div>
              <div id="viewport6" class="viewport">
                <div class="viewer-placeholder">
                  <i class="fas fa-image"></i>
                  <p>视图 3</p>
                </div>
              </div>
              <div id="viewport7" class="viewport">
                <div class="viewer-placeholder">
                  <i class="fas fa-image"></i>
                  <p>视图 4</p>
                </div>
              </div>
            </div>
          </div>
          <div
            v-show="false"
            class="image-navigation"
            id="imageNavigation"
            style="display: none"
          >
            <input
              type="range"
              id="imageSlider"
              min="0"
              max="0"
              value="0"
              class="image-slider"
            />
            <div class="navigation-info">
              <span id="currentImageIndex">1</span> /
              <span id="totalImages">1</span>
            </div>
          </div>
        </div>
        <!-- 底部工具栏 -->
        <div class="viewer-foot">
          <div
            class="mentbox1"
            :class="{ active: currentLayout === '1x1' }"
            @click="switchLayout('1x1')"
          >
            <img src="@/images/footment1.png" alt="" title="1×1 单视图" />
          </div>
          <div
            class="mentbox1"
            :class="{ active: currentLayout === '1x2' }"
            @click="switchLayout('1x2')"
          >
            <img src="@/images/footment2.png" alt="" title="2×2 单视图" />
          </div>
          <div
            class="mentbox1"
            :class="{ active: panToolActive }"
            @click="togglePanTool"
          >
            <img src="@/images/footment4.png" alt="" title="移动图像开关" />
          </div>
          <div class="mentbox1" @click="rotateImage">
            <img
              src="@/images/footment3.png"
              alt=""
              title="顺时针旋转90°"
              class="mentbox3img"
            />
          </div>
          <div
            class="mentbox1"
            :class="{ active: zoomToolActive }"
            @click="toggleZoomTool"
          >
            <img src="@/images/footment5.png" alt="" title="放大缩小开关" />
          </div>
          <div
            class="mentbox1"
            :class="{ active: windowLevelToolActive }"
            @click="toggleWindowLevelTool"
          >
            <img src="@/images/footment6.png" alt="" title="调整视窗曝光开关" />
          </div>
          <div
            class="mentbox1"
            :class="{ active: ellipseROIActive }"
            @click="activateEllipseROI"
          >
            <img src="@/images/footment7.png" alt="" title="ROI椭圆标记" />
          </div>
          <div
            class="mentbox1"
            :class="{ active: customBrushActive }"
            @click="activateCustomBrush"
          >
            <img src="@/images/footment8.png" alt="" title="自定义画笔标记" />
          </div>
          <div class="mentbox1" @click="restAction">
            <img
              src="@/images/footment9.png"
              alt=""
              title="重置操作"
              class="mentbox9img"
            />
          </div>
        </div>
      </section>
    </main>

    <!-- 加载指示器 -->
    <div id="loadingOverlay" class="loading-overlay" style="display: none">
      <div class="loading-spinner">
        <i class="fas fa-spinner fa-spin"></i>
        <p>正在加载DICOM文件...</p>
      </div>
    </div>
  </div>
</template>

<script>
  import * as cornerstone from 'cornerstone-core';
  import * as cornerstoneTools from 'cornerstone-tools';
  // import * as cornerstoneMath from 'cornerstone-math'; 在CornerstoneViewer中已经初始化了
  // import Hammer from 'hammerjs';在CornerstoneViewer中已经初始化了
  import { DicomProcessor } from '../utils/dicomProcessor.js';
  import { MultiViewManager } from '../utils/multiViewManager.js';
  import { ToolsManager } from '../utils/toolsManager.js';
  import { UIManager } from '../utils/uiManager.js';
  import ROIUtils from '../utils/roiutils.js';
  import { multiBrushManager } from '../utils/customBrushManager.js';

  // // 初始化 Cornerstone 在CornerstoneViewer中已经初始化了
  // cornerstoneTools.external.cornerstone = cornerstone;
  // cornerstoneTools.external.Hammer = Hammer;
  // cornerstoneTools.external.cornerstoneMath = cornerstoneMath;

  // // 初始化工具
  // cornerstoneTools.init({
  //   showSVGCursors: true,
  // });

  export default {
    name: 'DicomViewer',
    props: {
      baseUrl: {
        default: '',
        type: String,
      },
      fileNames: {
        default: () => {
          [];
        },
        type: Array,
      },
    },
    data() {
      return {
        processor: null,
        urls: null,
        seriesList: [],
        currentSeriesUID: null,
        currentLoadPromise: null, // 添加当前加载Promise的引用
        abortController: null, // 添加AbortController用于取消请求
        multiViewManager: null, // 添加 multiViewManager
        customBrushActive: false, // 自定义画笔是否激活
        panToolActive: false, // 平移工具是否激活
        zoomToolActive: false, // 缩放工具是否激活
        windowLevelToolActive: false, // 窗宽窗位工具是否激活
        ellipseROIActive: false, // 椭圆ROI工具是否激活
        currentLayout: '1x1', // 当前视口布局
        resizeTimeout: null, // 添加resizeTimeout
      };
    },
    mounted() {
      this.processor = new DicomWebProcessor(this);
      this.multiViewManager = this.processor.multiViewManager;

      // 初始化工具
      this.initializeTools();

      // 添加窗口大小改变监听器
      window.addEventListener('resize', this.handleWindowResize);
    },
    beforeDestroy() {
      // 清理事件监听器
      window.removeEventListener('resize', this.handleWindowResize);

      // 清理定时器
      if (this.resizeTimeout) {
        clearTimeout(this.resizeTimeout);
      }

      // 销毁画笔管理器
      multiBrushManager.destroy();
    },
    methods: {
      // 初始化工具
      initializeTools() {
        // 初始化ROI工具
        ROIUtils.initialize();

        // 初始化自定义画笔
        this.initializeCustomBrush();
      },

      // 初始化自定义画笔
      initializeCustomBrush() {
        // 等待DOM更新后初始化画笔
        this.$nextTick(() => {
          this.setupCustomBrush();
        });
      },

      // 设置自定义画笔
      setupCustomBrush() {
        // 获取所有视口
        const viewports = document.querySelectorAll('.viewport');
        console.log('设置自定义画笔 - 找到视口数量:', viewports.length);

        if (viewports.length > 0) {
          // 如果已经初始化过，先销毁
          multiBrushManager.destroy();

          // 为每个视口初始化画笔管理器
          viewports.forEach((viewport, index) => {
            const viewportId = viewport.id || `viewport${index + 1}`;
            multiBrushManager.initializeBrushForViewport(viewport, viewportId);
          });

          console.log('多画笔管理器初始化完成');

          // 如果画笔之前是激活状态，重新激活
          if (this.customBrushActive) {
            multiBrushManager.activate();
            console.log('重新激活自定义画笔');
          }
        } else {
          console.warn('未找到viewport，无法初始化画笔');
        }
      },

      async selectSeries(seriesUID) {
        if (this.processor) {
          await this.processor.selectSeries(seriesUID);

          // 选择序列后重新初始化画笔
          this.$nextTick(() => {
            this.restAction();
          });
        }
      },
      // 更换视图
      switchLayout(layout) {
        // 打印数组的深拷贝，确保获取的是打印时刻的状态

        if (this.multiViewManager) {
          this.multiViewManager.switchLayout(layout);
          this.currentLayout = layout; // 更新当前布局状态

          // 切换布局后重新初始化画笔
          this.$nextTick(() => {
            this.setupCustomBrush();
          });
        }
      },
      cancelLoading() {
        // 取消当前的加载
        if (this.abortController) {
          this.abortController.abort();
          this.abortController = null;
        }
        if (this.currentLoadPromise) {
          this.currentLoadPromise = null;
        }
        // 重置UI状态
        if (this.processor) {
          this.processor.uiManager.showLoading(false);
        }
      },
      loadUrlBtn() {
        // 如果正在加载，先取消
        this.cancelLoading();

        // 创建新的AbortController
        this.abortController = new AbortController();

        // 构建完整的URL数组
        const fileNames = this.fileNames;
        this.urls = fileNames.map((fileName) => this.baseUrl + fileName);

        if (this.urls.length > 0 && fileNames.length > 0) {
          // 保存当前加载Promise的引用
          this.currentLoadPromise = this.processor.handleUrlLoading(
            this.urls,
            this.abortController.signal
          );
          return this.currentLoadPromise;
        }
        return Promise.resolve();
      },
      // 通用工具激活方法
      activateTool(toolName, activateMethod) {
        if (this.multiViewManager) {
          const viewport =
            document.querySelector('.viewport.active') ||
            document.querySelector('.viewport');
          if (viewport) {
            try {
              cornerstoneTools.setToolActive(toolName, { mouseButtonMask: 1 });
              if (activateMethod) {
                this.multiViewManager[activateMethod]();
              }
            } catch (error) {
              console.warn(`${toolName} tool operation failed:`, error);
            }
          }
        }
      },
      // 切换平移工具
      togglePanTool() {
        if (this.panToolActive) {
          // 如果已激活，则停用
          this.deactivateAllTools();
        } else {
          // 如果未激活，则激活
          this.deactivateAllTools();
          this.activateTool('Pan', 'activatePanTool');
          this.panToolActive = true;
        }
      },
      // 切换缩放工具
      toggleZoomTool() {
        if (this.zoomToolActive) {
          // 如果已激活，则停用
          this.deactivateAllTools();
        } else {
          // 如果未激活，则激活
          this.deactivateAllTools();
          this.activateTool('Zoom', 'activateZoomTool');
          this.zoomToolActive = true;
        }
      },
      // 切换窗宽窗位工具
      toggleWindowLevelTool() {
        if (this.windowLevelToolActive) {
          // 如果已激活，则停用
          this.deactivateAllTools();
        } else {
          // 如果未激活，则激活
          this.deactivateAllTools();
          this.activateTool('Wwwc', 'activateWwwcTool');
          this.windowLevelToolActive = true;
        }
      },
      // 旋转图像
      rotateImage() {
        if (this.multiViewManager) {
          const viewport =
            document.querySelector('.viewport.active') ||
            document.querySelector('.viewport');
          if (viewport) {
            try {
              this.multiViewManager.rotate(90);
            } catch (error) {
              console.warn('Rotation failed:', error);
            }
          }
        }
      },

      // 激活椭圆ROI工具
      activateEllipseROI() {
        if (this.ellipseROIActive) {
          // 如果已激活，则停用
          this.deactivateAllTools();
        } else {
          // 如果未激活，则激活
          this.deactivateAllTools();
          ROIUtils.activateEllipseROI();
          this.ellipseROIActive = true;
        }
      },

      // 激活自定义画笔
      activateCustomBrush() {
        if (this.customBrushActive) {
          // 如果已激活，则停用
          this.deactivateAllTools();
        } else {
          // 如果未激活，则激活
          this.deactivateAllTools();

          // 确保画笔管理器已初始化
          this.setupCustomBrush();

          // 停用其他工具
          if (this.multiViewManager) {
            const viewport =
              document.querySelector('.viewport.active') ||
              document.querySelector('.viewport');
            if (viewport) {
              try {
                cornerstoneTools.setToolActive('Pan', { mouseButtonMask: 0 });
                cornerstoneTools.setToolActive('Zoom', { mouseButtonMask: 0 });
                cornerstoneTools.setToolActive('Wwwc', { mouseButtonMask: 0 });
                cornerstoneTools.setToolActive('EllipticalRoi', {
                  mouseButtonMask: 0,
                });
                cornerstoneTools.setToolActive('FreehandRoi', {
                  mouseButtonMask: 0,
                });
              } catch (error) {
                console.warn('停用其他工具失败:', error);
              }
            }
          }

          // 激活自定义画笔
          multiBrushManager.activate();
          this.customBrushActive = true;
          console.log('自定义画笔已激活');
        }
      },

      // 重置操作
      restAction() {
        // 清空所有自定义画笔绘制
        multiBrushManager.clearAll();
        // ROIUtils.clearAllROIs();

        // 清空所有ROI绘制
        if (this.multiViewManager) {
          const viewport = document.querySelector('.viewport.active canvas');

          if (viewport) {
            try {
              // 清空所有roi
              const enabledElements = cornerstone.getEnabledElements();

              // 遍历所有视口并清空EllipticalRoi标记
              enabledElements.forEach((element) => {
                if (element.viewport) {
                  cornerstoneTools.clearToolState(
                    element.element,
                    'EllipticalRoi'
                  );
                  cornerstone.updateImage(element.element);
                }
              });
              // 清空所哟ROI完成
              // 重置窗口
              // 直接重置全部视口
              // this.multiViewManager.initializeViewersForLayout(
              //   this.currentLayout
              // );
              // 先重置图像
              this.multiViewManager.resetView();
              // // 重置后默认激活窗宽窗位工具
              cornerstoneTools.setToolActive('Wwwc', { mouseButtonMask: 1 });
              this.multiViewManager.activateWwwcTool();

              // 刷新图像
            } catch (error) {
              console.warn('Reset operation failed:', error);
            }
          }
        }

        // 停用所有工具
        this.deactivateAllTools();

        // console.log('已清空所有绘制内容');
      },

      // 停用所有工具
      deactivateAllTools() {
        this.panToolActive = false;
        this.zoomToolActive = false;
        this.windowLevelToolActive = false;
        this.ellipseROIActive = false;
        this.customBrushActive = false;

        // 停用自定义画笔
        multiBrushManager.deactivate();
      },

      // 处理窗口大小改变
      handleWindowResize() {
        // 延迟执行，避免频繁调用
        clearTimeout(this.resizeTimeout);
        this.resizeTimeout = setTimeout(() => {
          // 更新所有画笔画布尺寸
          multiBrushManager.updateAllCanvasSizes();
        }, 100);
      },
    },
  };

  class DicomWebProcessor {
    constructor(vueInstance) {
      this.vue = vueInstance;
      this.dicomProcessor = new DicomProcessor();
      this.multiViewManager = new MultiViewManager();
      this.toolsManager = new ToolsManager();
      this.uiManager = new UIManager();

      this.currentSeries = null;
      this.currentImageIndex = 0;
      this.seriesData = new Map();
      this.currentLoadPromise = null;
      this.abortController = null;

      this.init();
    }

    init() {
      this.initializeComponents();
    }

    initializeComponents() {
      // 多视图管理器已在构造函数中初始化
      this.toolsManager.initialize(this.multiViewManager);

      // 将ROI管理器设为全局变量，以便在HTML中的onclick事件中使用
      window.roiManager = this.roiManager;
    }

    async displaySeriesList(seriesGroups) {
      // 将 Map 转换为数组格式
      const newSeriesList = Array.from(seriesGroups.entries()).map(
        ([seriesUID, series]) => ({
          seriesUID,
          ...series,
        })
      );
      console.log('Series List:', newSeriesList);

      // 使用 Vue 实例更新数据
      this.vue.seriesList = newSeriesList;

      // 如果有数据，自动选择第一个序列
      if (newSeriesList.length > 0) {
        await this.selectSeries(newSeriesList[0].seriesUID);
      }
    }

    async selectSeries(seriesUID) {
      // 更新UI选中状态
      this.vue.currentSeriesUID = seriesUID;

      // 从 seriesList 中找到对应的序列
      const selectedSeries = this.vue.seriesList.find(
        (series) => series.seriesUID === seriesUID
      );
      if (!selectedSeries) return;

      // 加载序列
      this.currentSeries = selectedSeries;
      this.currentImageIndex = 0;

      // 创建一个包含当前选中序列的Map，用于多视图显示
      const currentSeriesMap = new Map();
      currentSeriesMap.set(seriesUID, selectedSeries);

      await this.multiViewManager.setSeriesData(
        currentSeriesMap,
        0,
        (imageIndex) => {
          this.onImageChanged(imageIndex);
        }
      );

      // 显示智能窗宽窗位信息
      // this.showOptimalWindowLevelInfo();
    }

    // 当图像改变时的回调函数
    onImageChanged(imageIndex) {
      this.currentImageIndex = imageIndex;

      // 更新滑块位置
      const imageSlider = document.getElementById('imageSlider');
      imageSlider.value = imageIndex;

      // 更新当前图像索引显示
      document.getElementById('currentImageIndex').textContent = imageIndex + 1;

      // 更新图像信息
    }

    navigateToImage(index) {
      if (
        !this.currentSeries ||
        index < 0 ||
        index >= this.currentSeries.images.length
      ) {
        return;
      }

      // 使用MultiViewManager的导航方法
      this.multiViewManager.navigateToImage(index);
    }

    // 切换DICOM信息覆盖层显示
    toggleDicomOverlay() {
      const viewerElement = document.getElementById('dicomViewer');
      if (!viewerElement) return;

      // 获取所有视口
      const viewports = viewerElement.querySelectorAll('.viewport');

      // 遍历所有视口
      viewports.forEach((viewport) => {
        // 获取当前视口的覆盖层
        let overlay = viewport.querySelector('.dicom-overlay');

        // 如果覆盖层不存在，创建一个新的
        if (!overlay) {
          overlay = document.createElement('div');
          overlay.className = 'dicom-overlay';
          viewport.appendChild(overlay);

          // 创建四个角落的信息区域
          const corners = [
            'top-left',
            'top-right',
            'bottom-left',
            'bottom-right',
          ];
          corners.forEach((corner) => {
            const infoElement = document.createElement('div');
            infoElement.className = `dicom-info-${corner}`;
            overlay.appendChild(infoElement);
          });
        }

        // 切换覆盖层的显示状态
        overlay.style.display =
          overlay.style.display === 'none' ? 'block' : 'none';
      });
    }

    // 修改：处理URL加载
    // 支持多个DICOM文件的并行加载和处理
    async handleUrlLoading(urls, signal) {
      // 如果存在之前的请求，先取消它
      if (this.currentLoadPromise) {
        // 显示切换中提示
        this.uiManager.showLoading(true, '切换中，请勿频繁点击...');

        // 取消当前的加载
        if (this.abortController) {
          this.abortController.abort();
          this.abortController = null;
        }
        this.currentLoadPromise = null;
        // 不要在这里重置UI状态，保持加载提示显示
      }

      // 创建新的 AbortController
      this.abortController = new AbortController();
      const currentSignal = this.abortController.signal;

      // 显示新的加载提示
      this.uiManager.showLoading(true, '正在加载DICOM图片...');

      let isCancelled = false; // 添加取消状态标志

      try {
        const files = []; // 存储所有加载的文件
        let loadedCount = 0; // 已加载文件计数
        const totalCount = urls.length; // 总文件数

        // 创建一个请求队列处理函数
        const processQueue = async (urls) => {
          const results = [];
          const batchSize = 600; // 每批处理的请求数
          const delay = 1000; // 每批之间的延迟（毫秒）

          for (let i = 0; i < urls.length; i += batchSize) {
            // 检查是否已取消
            if (currentSignal.aborted) {
              throw new Error('加载已取消');
            }

            // 获取当前批次的URL
            const batch = urls.slice(i, i + batchSize);

            // 并行处理当前批次的请求
            const batchPromises = batch.map(async (url, index) => {
              try {
                const response = await fetch(url, { signal: currentSignal });
                const blob = await response.blob();
                const fileName =
                  url.split('/').pop() || `dicom_file_${i + index}`;
                const file = new File([blob], fileName, {
                  type: 'application/dicom',
                });
                file.url = url;
                return file;
              } catch (error) {
                if (
                  error.name === 'AbortError' ||
                  error.message === '加载已取消'
                ) {
                  throw error;
                }
                console.error(`加载文件失败 ${url}:`, error);
                return null;
              }
            });

            // 等待当前批次完成
            const batchResults = await Promise.all(batchPromises);
            results.push(...batchResults.filter(Boolean));

            // 更新加载进度
            loadedCount += batchResults.filter(Boolean).length;
            this.uiManager.showLoading(
              true,
              `正在加载DICOM图片... (${loadedCount}/${totalCount})`
            );

            // 如果不是最后一批，则等待指定的延迟时间
            if (i + batchSize < urls.length) {
              await new Promise((resolve) => setTimeout(resolve, delay));
            }
          }

          return results;
        };

        // 保存当前加载Promise的引用
        this.currentLoadPromise = processQueue(urls);

        // 处理所有URL
        const loadedFiles = await this.currentLoadPromise;

        // 检查是否已取消
        if (currentSignal.aborted) {
          throw new Error('加载已取消');
        }

        // 检查是否有文件成功加载
        if (loadedFiles.length === 0) {
          throw new Error('没有成功加载任何文件');
        }

        // 使用现有的文件处理逻辑处理所有文件
        const seriesGroups = await this.dicomProcessor.processFiles(
          loadedFiles
        );

        // 为每个序列生成封面图
        for (const [seriesUID, series] of seriesGroups.entries()) {
          if (series.images.length > 0) {
            const firstImage = series.images[0];

            // 从原始文件数组中查找对应的文件
            const originalFile = loadedFiles.find(
              (f) => f.name === firstImage.fileName
            );
            if (originalFile && originalFile.url) {
              firstImage.url = originalFile.url;
            }

            try {
              // 检查是否有必要的图像数据
              if (!firstImage.arrayBuffer) {
                console.error('缺少arrayBuffer数据');
                continue;
              }

              // 设置默认尺寸（如果缺少尺寸信息）
              if (!firstImage.rows || !firstImage.columns) {
                console.log('使用默认尺寸');
                // 根据模态类型设置不同的默认尺寸
                switch (series.modality) {
                  case 'CT':
                    firstImage.rows = 512;
                    firstImage.columns = 512;
                    break;
                  case 'MR':
                    firstImage.rows = 256;
                    firstImage.columns = 256;
                    break;
                  case 'CR':
                  case 'DX':
                    firstImage.rows = 2048;
                    firstImage.columns = 2048;
                    break;
                  default:
                    firstImage.rows = 512;
                    firstImage.columns = 512;
                }
              }

              // 确保有有效的URL
              if (!firstImage.url) {
                console.error('缺少图片URL');
                continue;
              }

              // 使用Cornerstone加载图像
              const imageId = `wadouri:${firstImage.url}`;
              console.log('Loading image with ID:', imageId);

              // 创建一个临时的canvas元素
              const canvas = document.createElement('canvas');
              const ctx = canvas.getContext('2d');

              // 设置canvas尺寸
              canvas.width = 40;
              canvas.height = 40;

              // 使用Cornerstone渲染图像到canvas
              const image = await cornerstone.loadImage(imageId);
              await cornerstone.renderToCanvas(canvas, image);

              // 转换为PNG格式的base64字符串
              const thumbnail = canvas.toDataURL('image/png');
              series.thumbnail = thumbnail;
            } catch (error) {
              console.error('生成封面图失败:', error, {
                seriesUID,
                imageData: firstImage,
                url: firstImage.url,
              });
            }
          }
        }

        // 更新UI显示
        await this.displaySeriesList(seriesGroups);
        this.seriesData = seriesGroups;

        // 将所有序列数据保存到MultiViewManager
        await this.multiViewManager.setAllSeriesData(seriesGroups);

        // 自动选择第一个序列
        if (seriesGroups.size > 0) {
          const firstSeriesUID = seriesGroups.keys().next().value;
          await this.selectSeries(firstSeriesUID);
        }

        // 显示成功消息
        this.uiManager.showSuccess(`成功加载DICOM图片`);
      } catch (error) {
        // 如果是取消操作，不显示错误消息
        if (error.name === 'AbortError' || error.message === '加载已取消') {
          console.log('加载已取消');
          isCancelled = true; // 设置取消状态
          // 如果是取消操作，保持加载状态显示
          this.uiManager.showLoading(true, '准备加载新的DICOM图片...');
        } else {
          console.error('加载DICOM图片时出错:', error);
          this.uiManager.showError('加载DICOM图片失败: ' + error.message);
        }
      } finally {
        // 清理当前请求的引用
        this.currentLoadPromise = null;
        this.abortController = null;
        // 只有在非取消状态下才关闭加载提示
        if (!isCancelled) {
          this.uiManager.showLoading(false);
        }
      }
    }

    // 生成封面图
    async generateThumbnail(imageData) {
      return new Promise((resolve, reject) => {
        try {
          // 检查图像数据是否完整
          if (!imageData) {
            console.error('图像数据为空');
            reject(new Error('图像数据为空'));
            return;
          }

          console.log('图像数据检查:', {
            hasPixelData: !!imageData.pixelData,
            columns: imageData.columns,
            rows: imageData.rows,
            pixelDataLength: imageData.pixelData
              ? imageData.pixelData.length
              : 0,
            windowWidth: imageData.windowWidth,
            windowCenter: imageData.windowCenter,
          });

          if (!imageData.pixelData || !imageData.columns || !imageData.rows) {
            console.error('图像数据不完整:', {
              pixelData: !!imageData.pixelData,
              columns: imageData.columns,
              rows: imageData.rows,
            });
            reject(new Error('图像数据不完整'));
            return;
          }

          // 创建一个临时的canvas元素
          const canvas = document.createElement('canvas');
          const ctx = canvas.getContext('2d');

          // 设置canvas尺寸
          canvas.width = 40;
          canvas.height = 40;

          // 获取像素数据
          const pixelData = imageData.pixelData;
          const width = imageData.columns;
          const height = imageData.rows;

          console.log('处理像素数据:', {
            width,
            height,
            pixelDataLength: pixelData.length,
            windowWidth: imageData.windowWidth,
            windowCenter: imageData.windowCenter,
          });

          // 创建新的Uint8ClampedArray来存储处理后的像素数据
          const processedData = new Uint8ClampedArray(width * height * 4);

          // 获取窗宽窗位
          const windowWidth = imageData.windowWidth || 400;
          const windowCenter = imageData.windowCenter || 40;

          // 计算窗宽窗位的范围
          const minValue = windowCenter - windowWidth / 2;
          const maxValue = windowCenter + windowWidth / 2;
          const range = maxValue - minValue;

          // 处理每个像素
          for (let i = 0; i < pixelData.length; i++) {
            // 应用窗宽窗位
            let value = pixelData[i];
            value = Math.max(minValue, Math.min(maxValue, value));
            value = ((value - minValue) / range) * 255;

            const index = i * 4;
            processedData[index] = value; // R
            processedData[index + 1] = value; // G
            processedData[index + 2] = value; // B
            processedData[index + 3] = 255; // A
          }

          // 创建ImageData
          const imageDataObj = new ImageData(processedData, width, height);

          // 将图像数据绘制到canvas
          ctx.putImageData(imageDataObj, 0, 0);

          // 转换为PNG格式的base64字符串
          const thumbnail = canvas.toDataURL('image/png');
          resolve(thumbnail);
        } catch (error) {
          console.error('生成封面图时出错:', error, {
            imageData: imageData
              ? {
                  hasPixelData: !!imageData.pixelData,
                  columns: imageData.columns,
                  rows: imageData.rows,
                  pixelDataLength: imageData.pixelData
                    ? imageData.pixelData.length
                    : 0,
                  windowWidth: imageData.windowWidth,
                  windowCenter: imageData.windowCenter,
                }
              : 'null',
          });
          reject(error);
        }
      });
    }
  }

  // 初始化应用
  document.addEventListener('DOMContentLoaded', () => {
    new DicomWebProcessor();
  });
</script>

<style scoped>
  /* 全局样式重置 */
  * {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
  }

  #appd {
    height: 100%;
    display: flex;
    flex-direction: column;
  }
  /* 主要内容区域 */
  .main-content {
    display: flex;
    overflow: hidden;
    height: 100%;
  }
  /* 侧边栏样式 */
  .sidebar {
    background: #40495a;
    backdrop-filter: blur(10px);
    display: flex;
    flex-direction: column;
    overflow: hidden;
    width: 300px;
    padding: 18px;
  }
  .series-list {
    overflow-y: auto;
  }
  .series-item {
    margin-bottom: 12px;
    cursor: pointer;
    display: flex;
    align-items: center;
    font-size: 12px;
    color: #ffffff;
  }
  .series-thumbnail {
    width: 40px;
    height: 40px;
    overflow: hidden;
    flex-shrink: 0;
  }
  .series-thumbnail img {
    width: 100%;
    height: 100%;
    object-fit: cover;
  }
  .series-content {
    min-width: 0;
    margin-left: 10px;
  }
  .series-title {
    font-weight: 600;
    margin-bottom: 8px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .series-info {
    width: 145px;
    text-align: right;
  }
  /* 图像查看器样式 */
  .viewer-container {
    display: flex;
    flex-direction: column;
    overflow: hidden;
    height: 100%;
    width: 100%;
    position: relative;
  }
  .viewer-foot {
    position: absolute;
    bottom: 0px;
    left: 0px;
    width: 100%;
    height: 46px;
    background-color: #222222;
    display: flex;
    align-items: center;
    justify-content: space-around;
  }

  .navigation-info {
    text-align: center;
    color: #6c757d;
    font-size: 14px;
  }

  /* 加载指示器 */
  .loading-spinner {
    background: white;
    padding: 32px;
    border-radius: 12px;
    text-align: center;
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
  }

  .loading-spinner i {
    font-size: 32px;
    color: #3498db;
    margin-bottom: 16px;
  }

  .loading-spinner p {
    color: #495057;
    font-weight: 500;
  }

  /* ROI工具样式 */
  .roi-tools {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 8px;
    margin-bottom: 16px;
  }

  .roi-controls {
    display: flex;
    gap: 8px;
    margin-bottom: 16px;
    flex-wrap: wrap;
  }

  .roi-stats {
    background: rgba(52, 152, 219, 0.1);
    border-radius: 6px;
    padding: 12px;
    margin-bottom: 16px;
    border: 1px solid rgba(52, 152, 219, 0.2);
  }

  .stats-item {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 8px;
  }

  .stats-label {
    font-size: 14px;
    color: #6c757d;
    font-weight: 500;
  }

  .roi-list-container {
    margin-top: 16px;
  }

  .roi-list-container h5 {
    margin: 0 0 12px 0;
    font-size: 14px;
    color: #495057;
    display: flex;
    align-items: center;
    gap: 8px;
  }

  .empty-roi-list {
    padding: 32px;
    text-align: center;
    color: #6c757d;
    font-size: 14px;
    font-style: italic;
  }

  .roi-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12px;
    border-bottom: 1px solid #e9ecef;
    cursor: pointer;
    transition: all 0.2s ease;
    background: white;
  }

  .roi-name {
    font-weight: 500;
    font-size: 14px;
    color: #495057;
    margin-bottom: 4px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  .roi-stats {
    font-size: 12px;
    color: #6c757d;
  }

  .roi-type-stats {
    font-size: 12px;
    color: #6c757d;
  }

  .roi-action-btn {
    padding: 4px;
    border: none;
    background: transparent;
    color: #6c757d;
    cursor: pointer;
    border-radius: 3px;
    transition: all 0.2s ease;
    width: 24px;
    height: 24px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 12px;
  }

  .roi-context-menu .menu-item {
    padding: 12px 16px;
    cursor: pointer;
    transition: background-color 0.2s ease;
    font-size: 14px;
    color: #495057;
    border-bottom: 1px solid #f8f9fa;
  }

  .roi-details-container {
    margin-top: 16px;
    border-top: 1px solid #e9ecef;
    padding-top: 16px;
  }

  .roi-details-container h5 {
    margin: 0 0 12px 0;
    font-size: 14px;
    color: #495057;
    display: flex;
    align-items: center;
    gap: 8px;
  }

  .roi-details-panel {
    background: #f8f9fa;
    border-radius: 6px;
    padding: 16px;
    border: 1px solid #e9ecef;
  }

  .detail-group {
    margin-bottom: 16px;
  }

  .detail-group h6 {
    margin: 0 0 8px 0;
    font-size: 14px;
    color: #495057;
    font-weight: 600;
    padding-bottom: 4px;
    border-bottom: 1px solid #dee2e6;
  }

  .detail-item {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 4px 0;
    font-size: 13px;
  }

  /* 视图布局控制 */

  /* 多视图布局样式 */
  .viewport-container {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    display: flex;
    background: #000;
  }

  .viewport {
    position: relative;
    background: #000;
    overflow: hidden;
    box-sizing: border-box; /* 使 padding 和 border 包含在宽度内 */
  }

  .viewport .viewer-placeholder {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    text-align: center;
    color: #6c757d;
    font-size: 14px;
  }

  .viewport .viewer-placeholder i {
    font-size: 32px;
    margin-bottom: 8px;
    opacity: 0.5;
  }

  /* 视图边框高亮 */
  .viewport.active {
    border: 1px solid#00ff00;
  }

  .viewport:hover {
    box-shadow: 0 0 0 2px rgba(52, 152, 219, 0.5);
  }

  /* DICOM信息覆盖层 */
  .dicom-overlay {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
    z-index: 10;
    font-family: 'Courier New', monospace;
    font-size: 12px;
    color: #00ff00;
    text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.8);
  }

  .dicom-info-top-left,
  .dicom-info-top-right,
  .dicom-info-bottom-left,
  .dicom-info-bottom-right {
    position: absolute;
    padding: 8px;
    line-height: 1.4;
    white-space: pre-line;
    background: rgba(0, 0, 0, 0.3);
    border-radius: 4px;
  }

  /* 工具提示 */
  .tooltip {
    position: relative;
  }

  .tooltip::after {
    content: attr(title);
    position: absolute;
    bottom: 100%;
    left: 50%;
    transform: translateX(-50%);
    background: rgba(0, 0, 0, 0.8);
    color: white;
    padding: 8px;
    border-radius: 4px;
    font-size: 13px;
    white-space: nowrap;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.3s;
    z-index: 1000;
  }

  /* 滑块样式 */
  .slider {
    width: 100%;
    margin-bottom: 8px;
    -webkit-appearance: none;
    appearance: none;
    height: 6px;
    border-radius: 3px;
    background: #ddd;
    outline: none;
  }

  .slider::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 18px;
    height: 18px;
    border-radius: 50%;
    background: #3498db;
    cursor: pointer;
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
  }

  .slider::-moz-range-thumb {
    width: 18px;
    height: 18px;
    border-radius: 50%;
    background: #3498db;
    cursor: pointer;
    border: none;
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
  }

  .preset-btn:hover {
    background: #3498db;
    color: white;
    border-color: #3498db;
  }

  .preset-btn.auto-preset {
    background: linear-gradient(135deg, #e74c3c, #c0392b);
    color: white;
    border-color: #e74c3c;
    font-weight: 600;
    grid-column: 1 / -1;
  }

  .preset-btn.auto-preset:hover {
    background: linear-gradient(135deg, #c0392b, #a93226);
    transform: translateY(-1px);
    box-shadow: 0 4px 12px rgba(231, 76, 60, 0.3);
  }

  /* 加载遮罩 */
  .loading-overlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(0, 0, 0, 0.7);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 1000;
  }

  /* 图像查看器主容器 */
  .viewer-main {
    display: flex;
    flex-direction: column;
    position: relative;
    overflow: hidden;
    width: 100%;
    height: 93%;
  }

  .dicom-viewer {
    flex: 1;
    position: relative;
    background: #000;
    overflow: hidden;
  }

  .viewer-placeholder {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    text-align: center;
    color: #6c757d;
  }

  .viewer-placeholder i {
    font-size: 64px;
    margin-bottom: 16px;
    opacity: 0.5;
  }

  /* 图像滑块 */
  .image-slider {
    width: 100%;
    margin-bottom: 8px;
  }
  .layout-1x1 {
    display: flex;
  }

  .layout-1x1 .viewport {
    flex: 1;
    width: 100%;
    height: 100%;
  }

  .layout-1x2 {
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-template-rows: 1fr;
  }

  .layout-1x2 .viewport {
    width: 100%;
    height: 100%;
  }

  .layout-2x2 {
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-template-rows: 1fr 1fr;
  }

  .layout-2x2 .viewport {
    width: 100%;
    height: 100%;
  }

  .viewport {
    position: relative;
    background: #000;
    overflow: hidden;
  }
  .mentbox1 {
    width: 40px;
    height: 40px;
    display: flex;
    align-items: center;
    justify-content: center;
  }
  .mentbox1 img {
    width: 24px;
    height: 24px;
    display: block;
  }
  .mentbox3img {
    width: 39px !important;
    height: 21px !important;
  }
  .mentbox9img {
    width: 31px !important;
    height: 21px !important;
  }
  /* 激活状态的工具栏按钮 */
  .mentbox1.active {
    background: rgb(124 124 131 / 79%);
    border-radius: 4px;
    width: 40px;
    height: 40px;
    display: flex;
    align-items: center;
    justify-content: center;
  }
</style>
